package cn.chair.controller.advice;

import cn.chair.model.Result;
import life.innovation.exception.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@ControllerAdvice
public class GlobalExceptionHandler {
	
	private static final Logger log = LoggerFactory.getLogger("appLogger");
    private static final Logger elog = LoggerFactory.getLogger("errorLogger");
	
	private Result getResult(Exception e, Integer resultCode, String errorMsg) {
		elog.error(e.getMessage(), e);
		
		Result result = new Result();
		
		if (errorMsg == null) {
			result.setErrorMessage(e.getMessage());
		} else {
			result.setErrorMessage(errorMsg);
		}
		
		if (resultCode == null) {
			result.setResultCode(Result.ERROR_OTHER);
		} else {
			result.setResultCode(resultCode);
		}
		
		return result;
	}

	private Result getFailResult(Exception e, Integer resultCode, String errorMsg, String extra) {
		elog.error(e.getMessage(), e);

		Result result = new Result();

		if (errorMsg == null) {
			result.setErrorMessage(e.getMessage());
		} else {
			result.setErrorMessage(errorMsg);
		}

		if (resultCode == null) {
			result.setResultCode(Result.ERROR_OTHER);
		} else {
			result.setResultCode(resultCode);
		}

		if (extra != null) {
			result.setExtra(extra);
		}

		return result;
	}
	
	@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	@ResponseBody
	public Result missingParamterException(Exception e, HttpServletRequest request, HttpServletResponse resp) {
		return getResult(e, Result.ERROR_CODE_MISSING_PARAM, Result.MSG_MISSING_PARAM);
	} 
    
    @ExceptionHandler(InvalidInputException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public Result invalidInputException(InvalidInputException e, HttpServletRequest request, HttpServletResponse resp) {
        return getResult(e, e.getErrorCode(), null);
    }
	
	@ExceptionHandler(FailedDependencyException.class)
    @ResponseStatus(HttpStatus.FAILED_DEPENDENCY)
    @ResponseBody
    public Result failedDependencyException(FailedDependencyException e, HttpServletRequest request, HttpServletResponse resp) {
//        return getResult(e, e.getErrorCode(), e.getMessage());
		return getFailResult(e, e.getErrorCode(), e.getMessage(), e.getExtra());
    }

    @ExceptionHandler(UnauthenticatedException.class)
	@ResponseStatus(HttpStatus.UNAUTHORIZED)
	@ResponseBody
	public Result unauthenticatedException(UnauthenticatedException e, HttpServletRequest request, HttpServletResponse resp) {
		return getResult(e, e.getErrorCode(), null);
	}
	
	@ExceptionHandler(UnauthorizedException.class)
    @ResponseStatus(HttpStatus.FORBIDDEN)
    @ResponseBody
    public Result unauthorizedException(UnauthorizedException e, HttpServletRequest request, HttpServletResponse resp) {
        return getResult(e, e.getErrorCode(), null);
    }
	
	@ExceptionHandler(ResourceNotFoundException.class)
	@ResponseStatus(HttpStatus.NOT_FOUND)
	@ResponseBody
	public Result notFoundException(ResourceNotFoundException e, HttpServletRequest request, HttpServletResponse resp) {
		return getResult(e, e.getErrorCode(), null);
	}
	
	@ExceptionHandler(BaseException.class)
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	@ResponseBody
	public Result handleBaseException(BaseException e, HttpServletRequest request, HttpServletResponse resp) {
		return getResult(e, e.getErrorCode(), null);
	}

    @ExceptionHandler(NullPointerException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public Result nullPointerException(Exception e, HttpServletRequest request, HttpServletResponse resp) {
        elog.error(e.getMessage(), e);
        return getResult(e, null, null);
    }

	@ExceptionHandler(Exception.class)
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	@ResponseBody
	public Result handleException(Exception e, HttpServletRequest request, HttpServletResponse resp) {
		elog.error(e.getMessage(), e);
		return getResult(e, null, null);
	}
}
